/********************************************************************************
 * Copyright(c) 2020-2025 BST All rights reserved.
 * - Filename
 * - Author
 * - Version V1.0.0
 * - Date    2024/08/28
 * - Brief
 * - FunctionList:
 ******************************************************************************
 * History:
 *
 *
 *
 ******************************************************************************
 */
#include <condition_variable>
#include <fstream>
#include <mutex>
#include <string>

#include "Recorder.h"
#include "SyncUdpClient.h"
#include "nlohmann/json.hpp"

#define BACKWARD_HAS_DW 1
#include "backward.hpp"
namespace backward {
backward::SignalHandling sh;
}

using namespace std;
using njson = nlohmann::json;

mutex mExitMutex;
condition_variable mExitCond;
bool mExit = false;
std::shared_ptr<lidar::LidarRecoder> recoder{nullptr};
void getSyncResponse(std::string &response);

static void sigterm_handler(int sig) {
  {
    lock_guard<mutex> lock(mExitMutex);
    mExit = true;
  }
  mExitCond.notify_all();
}

void getSyncResponse(std::string &response) {
  if (recoder != nullptr) {
    recoder->control(response);
  }
}

int main(int argc, char *argv[]) {
  mExit = false;
  signal(SIGINT, sigterm_handler);
  std::string cfgPath;
  if (argc != 2) {
    std::cout << "Please input config json file.." << std::endl;
    return 0;
  }
  printf("start record ...\n");
  cfgPath = argv[1];
  std::fstream cfgStream{cfgPath};
  njson cfg;
  try {
    cfgStream >> cfg;
  } catch (const std::exception &e) {
    std::cout << "get config from " << cfgPath << "  error: " << e.what()
              << std::endl;
    return -1;
  }
  std::cout << "get config from " << cfgPath << std::endl;
  auto syncServerPort = cfg["dump"]["syncPort"].get<int>();
  auto recordPath = cfg["dump"]["path"].get<std::string>();
  auto dbFileEnable = cfg["dump"]["dbfile"].get<bool>();
  auto lidarObj = cfg.at("lidar");

  std::vector<std::unique_ptr<lidar::Lidar>> lidar{};
  for (auto &elm : lidarObj) {
    int id = elm.at("id");
    std::string ip = elm.at("ip");
    std::string direction = elm.at("direction");
    int devPort = elm.at("dev_port");
    int dataPort = elm.at("data_port");
    std::string interface = elm.at("interface");
    std::string type = elm.at("type");
    if (type == "apollo") {
      lidar.emplace_back(lidar::Lidar::Builder()
                             .type(type)
                             .id(id)
                             .ip(ip)
                             .interface(interface)
                             .model();
                             .build());
    }
    printf("typd:%s,id:%d,ip:%s,interface:%s\n", type.c_str(), id, ip.c_str(),
           interface.c_str());
  }

  recoder = std::make_shared<lidar::LidarRecoder>(std::move(lidar), recordPath);
  /*sync*/
  // vudp::vudpClient udpClientObj(syncServerPort);
  // udpClientObj.responseCallback(getSyncResponse);
  // udpClientObj.vudpClientStart();
  /*recorder*/
  printf("start record ...\n");
  // recoder->setDbFile(dbFileEnable);
  // recoder->start();
  // recoder->control("StartRecord");
  printf("start record ...\n");

  unique_lock<mutex> lock(mExitMutex);
  mExitCond.wait(lock, [&] { return mExit; });
  recoder->control("StartStop");
  recoder->stop();
  std::cout << "~~~ main exit ~~~" << std::endl;
  return 0;
}